package main

import (
	"crypto/rand"
	"encoding/json"
	"math/big"
	"os"
	"strconv"
	"time"

	"github.com/lxn/walk"
)

var (
	nameTimer  TimerID
	groupTimer TimerID
	ttsTimeout TimerID
	nameList   []string // 作为待点名单使用，点名时点此数组中的名
	labelList  []string
	sheetsList []string
)

var mw = new(MainWindow)

var nameIndex = 0
var filepath = "D:\\random-name-snapshot.json"

type MainWindow struct {
	*walk.MainWindow
	ui mainWindowUI
}

func runMainWindow() (int, error) {
	mw.init()
	defer mw.Dispose()

	// 初始化配置文件到ui

	// 初始化组号设置
	err := mw.ui.spinBox.SetValue(float64(c.Groups))
	ifErr(err)
	err = mw.ui.spinBox_2.SetValue(float64(c.Nums))
	ifErr(err)
	// 初始化点名设置
	mw.ui.ckbox.SetChecked(c.Animate)
	mw.ui.usetts.SetChecked(c.UseTTS)
	mw.ui.repeatBox.SetChecked(c.Repeat)
	// 将所有姓名和表取出到数组中
	updateNameList()
	updateLabelList()
	updateSheetList()
	updateNameTable()
	// 初始化combobox
	err = mw.ui.comboBox.SetModel(sheetsList)
	ifErr(err)
	err = mw.ui.comboBox.SetCurrentIndex(c.SelectedSheet)
	ifErr(err)
	err = mw.ui.numLabel_1.SetText(strconv.Itoa(len(nameList)) + "人")
	ifErr(err)
	err = mw.ui.listLabel.SetText("共" + strconv.Itoa(len(nameList)) + "人")
	ifErr(err)

	// 绑定事件
	mw.ui.spinBox.ValueChanged().Attach(func() {
		c.Groups = int(mw.ui.spinBox.Value())
		saveConfig()
	})
	mw.ui.spinBox_2.ValueChanged().Attach(func() {
		c.Nums = int(mw.ui.spinBox_2.Value())
		saveConfig()
	})

	var minNum = mw.ui.minBox.Value()
	var maxNum = mw.ui.maxBox.Value()

	// TODO: Do further required setup, e.g. for event handling, here.

	mw.ui.editBtn.Clicked().Attach(showEdit)

	// 更改筛选项
	mw.ui.comboBox_2.CurrentIndexChanged().Attach(func() {
		if mw.ui.comboBox_2.CurrentIndex() < 0 { // 女娲
			return
		}
		updateNameList()
		err = mw.ui.numLabel_1.SetText(strconv.Itoa(len(nameList)) + "人")
		ifErr(err)
	})

	// 点名
	mw.ui.pushButton.Clicked().Attach(randNameEvent)
	mw.ui.lineEdit.KeyDown().Attach(func(key walk.Key) {
		walk.MsgBox(mw, "KeyDown", "KeyDown: "+key.String(), walk.MsgBoxIconInformation)
		if key == walk.KeyNext {
			randNameEvent()
		}
	})

	mw.ui.filterCkbox.CheckedChanged().Attach(func() {
		if mw.ui.filterCkbox.Checked() {
			if len(labelList) == 0 {
				walk.MsgBox(mw, "不可使用筛选", "此表中没有设置筛选标签", walk.MsgBoxIconWarning)
				mw.ui.filterCkbox.SetChecked(false)
				return
			}
			mw.ui.comboBox_2.SetEnabled(true)
		} else {
			mw.ui.comboBox_2.SetEnabled(false)
		}
		updateNameList()
		err = mw.ui.numLabel_1.SetText(strconv.Itoa(len(nameList)) + "人")
		ifErr(err)
	})

	mw.ui.minBox.ValueChanged().Attach(func() {
		if mw.ui.minBox.Value() >= maxNum {
			walk.MsgBox(mw.MainWindow, "错误", "最小值不能大于最大值", walk.MsgBoxIconWarning)
			err := mw.ui.minBox.SetValue(minNum)
			ifErr(err)
			return
		}
		minNum = mw.ui.minBox.Value()
	})

	mw.ui.maxBox.ValueChanged().Attach(func() {
		if mw.ui.maxBox.Value() <= minNum {
			walk.MsgBox(mw.MainWindow, "错误", "最大值不能小于最小值", walk.MsgBoxIconWarning)
			err := mw.ui.maxBox.SetValue(maxNum)
			ifErr(err)
			return
		}
		maxNum = mw.ui.maxBox.Value()
	})

	// 抽随机数
	mw.ui.chnumBtn.Clicked().Attach(func() {
		n, err := rand.Int(rand.Reader, big.NewInt(int64(maxNum-minNum)+1))
		ifErr(err)
		n = new(big.Int).Add(n, big.NewInt(int64(minNum)))
		r := n.String()
		err = mw.ui.rnumLabel.SetText(r)
		ifErr(err)
		invokeTTS(r)
	})

	// 抽组
	mw.ui.startGroupBtn.Clicked().Attach(func() {
		if c.Animate {
			if mw.ui.startGroupBtn.Text() == `开始抽号` {
				err := mw.ui.startGroupBtn.SetText(`停止抽号`)
				ifErr(err)
				groupTimer = GsetInterval(func() { randGroup(mw) }, time.Millisecond*c.Timer)
				return
			} else {
				err := mw.ui.startGroupBtn.SetText(`开始抽号`)
				ifErr(err)
				GclearInterval(groupTimer)
			}
		} else {
			randGroup(mw)
		}
		invokeTTS(mw.ui.groupLabel.Text() + "组" + mw.ui.numLabel.Text() + "号")
	})

	// 改变设置
	mw.ui.ckbox.CheckedChanged().Attach(func() {
		c.Animate = mw.ui.ckbox.Checked()
		saveConfig()
	})
	mw.ui.usetts.CheckedChanged().Attach(func() {
		c.UseTTS = mw.ui.usetts.Checked()
		saveConfig()
	})
	mw.ui.repeatBox.CheckedChanged().Attach(func() {
		if mw.ui.repeatBox.Checked() {
			c.Repeat = mw.ui.repeatBox.Checked()
			saveConfig()
		} else {
			updateNameList()
		}
	})

	// 更改姓名表选中项
	mw.ui.comboBox.CurrentIndexChanged().Attach(func() {
		if mw.ui.comboBox.CurrentIndex() < 0 {
			return
		}
		c.SelectedSheet = mw.ui.comboBox.CurrentIndex()
		saveConfig()
		updateNameTable()
		updateLabelList()
		updateNameList()
		mw.ui.filterCkbox.SetChecked(false)
		err = mw.ui.listLabel.SetText("共" + strconv.Itoa(len(nameList)) + "人")
		ifErr(err)
		err = mw.ui.numLabel_1.SetText(strconv.Itoa(len(nameList)) + "人")
		ifErr(err)
	})

	mw.Show()

	return mw.Run(), nil
}

func main() {
	// check file config.json
	if _, err := os.Stat(filepath); os.IsNotExist(err) {
		c = &config{
			NameSheets: []nameSheet{},
			Groups:     3,
			Nums:       5,
			Animate:    true,
			UseTTS:     true,
			Repeat:     false,
			Timer:      time.Duration(20),
			Timeout:    time.Duration(500),
		}
		saveConfig()
	}

	// 读取配置文件
	data, err := os.ReadFile(filepath)
	ifErr(err)
	err = json.Unmarshal(data, &c)
	ifErr(err)

	// 合法化配置文件
	if len(c.NameSheets) == 0 {
		addSheet("空姓名表")
	}
	saveConfig()

	showFloatWindow()
	_, err = runMainWindow()
	ifErr(err)
}

// 保存配置文件
func saveConfig() {
	data, err := json.MarshalIndent(c, "", "  ")
	ifErr(err)
	err = os.WriteFile(filepath, data, 0644)
	ifErr(err)
}

// 检查姓名列表是否为空
func checkNameList() {
	if len(nameList) == 0 {
		updateNameList()
		if len(nameList) == 0 {
			walk.MsgBox(mw.MainWindow, "错误", "请先填写姓名", walk.MsgBoxIconWarning)
			return
		} else {
			walk.MsgBox(mw.MainWindow, "提示", "已经点完所有名，名单自动重置", walk.MsgBoxIconInformation)
		}
	}
}

// 点名（事件用）
func randNameEvent() {
	checkNameList()
	if c.Animate {
		if mw.ui.pushButton.Text() == `开始点名` {
			err := mw.ui.pushButton.SetText(`停止点名`)
			ifErr(err)
			mw.ui.comboBox_2.SetEnabled(false)
			mw.ui.filterCkbox.SetEnabled(false)
			nameTimer = GsetInterval(func() {
				if nameIndex >= len(nameList) {
					nameIndex = 0
				}
				err := mw.ui.nameLabel.SetText(nameList[nameIndex])
				ifErr(err)
				nameIndex++
			}, time.Millisecond*c.Timer)
			return
		} else {
			err := mw.ui.pushButton.SetText(`开始点名`)
			ifErr(err)
			mw.ui.comboBox_2.SetEnabled(true)
			mw.ui.filterCkbox.SetEnabled(true)
			GclearInterval(nameTimer)
		}
	}
	err = mw.ui.nameLabel.SetText(randName())
	ifErr(err)
}

// 点名
func randName() string {
	var i int
	n, err := rand.Int(rand.Reader, big.NewInt(int64(len(nameList))))
	ifErr(err)
	i, err = strconv.Atoi(n.String())
	ifErr(err)
	//err = mw.ui.nameLabel.SetText(nameList[i])
	//ifErr(err)
	name := nameList[i]
	if c.Repeat {
		nameList = append(nameList[:i], nameList[i+1:]...)
	}
	nameIndex = 0
	invokeTTS(name)
	return name
}

// 抽取组号
func randGroup(mw *MainWindow) {
	group, err := rand.Int(rand.Reader, big.NewInt(int64(c.Groups)))
	ifErr(err)
	group = new(big.Int).Add(group, big.NewInt(1))
	num, err := rand.Int(rand.Reader, big.NewInt(int64(c.Nums)))
	ifErr(err)
	num = new(big.Int).Add(num, big.NewInt(1))

	err = mw.ui.groupLabel.SetText(group.String())
	ifErr(err)
	err = mw.ui.numLabel.SetText(num.String())
	ifErr(err)
}

// 防抖调用tts
func invokeTTS(text string) {
	if c.UseTTS {
		if ttsTimeout != 0 {
			GclearTimeout(ttsTimeout)
			ttsTimeout = 0
		}
		ttsTimeout = GsetTimeout(func() {
			go tts(text)
			ttsTimeout = 0
		}, time.Millisecond*c.Timeout)
	}
}

// 更新姓名数组（按筛选）
func updateNameList() {
	nameList = []string{}
	if mw.ui.filterCkbox.Checked() {
		nameList = c.NameSheets[mw.ui.comboBox.CurrentIndex()].LabelGroups[c.GetGroup(mw.ui.comboBox.CurrentIndex(), labelList[mw.ui.comboBox_2.CurrentIndex()])].Names
	} else {
		for _, group := range c.NameSheets[c.SelectedSheet].LabelGroups {
			for _, name := range group.Names {
				nameList = append(nameList, name)
			}
		}
	}
}

// 更新姓名表数组
func updateSheetList() {
	sheetsList = []string{}
	for _, sheet := range c.NameSheets {
		sheetsList = append(sheetsList, sheet.Sheet)
	}
}

// 更新姓名表格模型
func updateNameTable() {
	var nm []NameTableItem
	for _, g := range c.NameSheets[c.SelectedSheet].LabelGroups {
		for _, n := range g.Names {
			nm = append(nm, NameTableItem{
				Name:  n,
				Label: g.Label,
			})
		}
	}
	nameTable.SetValue(nm)
}

// 更新标签数组
func updateLabelList() {
	labelList = []string{}
	for _, g := range c.NameSheets[c.SelectedSheet].LabelGroups {
		if g.Label == "" {
			continue
		}
		labelList = append(labelList, g.Label)
	}
	err := mw.ui.comboBox_2.SetModel(labelList)
	ifErr(err)
	if len(labelList) > 0 {
		err = mw.ui.comboBox_2.SetCurrentIndex(0)
		ifErr(err)
	}
}
